import { CreateMeta, HoleMeta } from '@/model/meta/MetaClass';
import AModelFmulaUtils from '@/model/utils/AModelFmulaUtils';
import { Quaternion, Vector3 } from 'three';
import AluGeoUtil from '../utils/AluGeoUtil';


/** L圆弧角铝参数*/
interface LRP {
    /** 长2*/
    x_l: number,
    /** 宽2*/
    x_w: number,
    /** 宽1*/
    z_w: number,
    /** 长1*/
    z_l: number,
    /** 边框厚度*/
    t: number,
    /** 边框孔直径*/
    tr: number,
    /** 圆弧半径*/
    rr: number,
    /** 边框孔距非接触面距*/
    td: number,
    /** 夹角*/
    angle: number,
    /** 高*/
    h: number,
    /** x_xoz上边偏移量*/
    x_xoz_offX: number,
    /** z_xoz上边偏移量*/
    z_xoz_offX: number
}


/** L圆弧角铝网格*/
export default class LRAluGeometry {

    geometryMeta: GeometryReturnMeta<Array<any>>;
    // LRP

    private _lrp: Partial<AIBasicParams>;

    constructor(data: AIBasicParams) {

        this.geometryMeta = {
            vertices: [],
            indices: [],
            meshface: []
        };

        this.setParams(data);
        this.create();

        this.setDuan(data);
    }


    /** 创建*/
    private create() {
        this.x_xoz();
        this.xoy();

        this.z_xoz();
        this.zoy();

        this.r_com();
    }

    private setDuan(data: AIBasicParams) {
        data["duan"] = [
            0, 0, 0,
            data.L2, 0, 0,
            0, 0, data.L1
        ];
        data["zhong"] = {
            L1: [
                {
                    pointer: [data.W1/2, 0, data.L1],
                    center: [data.W1 / 2, 0, data.L1/2]
                },
            ],
            L2: [
                {
                    pointer: [data.L2, 0, data.W2 / 2],
                    center: [data.L2 / 2, 0, data.W2 / 2]
                },
            ]
        }

    }


    /** x向xoz板 (长2宽)*/
    private x_xoz() {
        let w = +this._lrp.L2;
        let l = +this._lrp.W2;
        let t = +this._lrp.bkT;
        let r = (+this._lrp.angle1) * -1;
        let bkd = (+this._lrp.BKDia) * 0.5;
        let b_dis = +this._lrp["p_c2kkbj"];




        let back = [
            0, 0, 0, w, 0, 0, w, l, 0, this._lrp['x_xoz_offX'], l, 0,
        ];

        let front = [
            0, 0, t, w, 0, t, w, l, t, this._lrp['x_xoz_offX'], l, t,
        ];

        // this._lrp["p_c2kk"] = this._lrp["o_p_c2kk"];

        let holes = AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c2kk"], w);
        let filterHole = AluGeoUtil.filterHoleLessMore(this._lrp['x_xoz_offX'], w - bkd, holes);
        holes = AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c2kk"], w, 2, this._lrp, "p_c2kk", Math.abs(filterHole.length - holes.length));
        holes = AluGeoUtil.reverseHole(w, holes);

        let h = new HoleMeta(bkd, l - b_dis, filterHole, "x");
        let c = new CreateMeta(t, front, back, h);
        let result = AluGeoUtil.createBoardWithHole(c);

        //绕x旋转90度
        let xr = 0.5 * Math.PI;
        let sr = Math.sin(xr);
        let cr = Math.cos(xr);
        for (let i: number = 0; i < result.vertices.length; i += 3) {
            let y = result.vertices[i + 1];
            let z = result.vertices[i + 2];

            result.vertices[i + 1] = y * cr - sr * z;
            result.vertices[i + 2] = sr * y + z * cr;
        }

        let count = this.geometryMeta.vertices.length;
        this.geometryMeta.indices.push(...result.indices.map((value) => { value += count / 3; return value }));
        this.geometryMeta.vertices.push(...result.vertices);
    }


    /** z向xoz板(长1宽)*/
    private z_xoz() {
        let w = +this._lrp.L1;
        let l = +this._lrp.W1;
        let t = +this._lrp.bkT;
        let bkd = (+this._lrp.BKDia) * 0.5;
        let b_dis = +this._lrp["p_c1kkbj"];

        let back = [
            this._lrp['z_xoz_offX'], 0, 0, w, 0, 0, w, l, 0, 0, l, 0,
        ];

        let front = [
            this._lrp['z_xoz_offX'], 0, t, w, 0, t, w, l, t, 0, l, t,
        ];



        let holes = AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c1kk"], w);
        let filterHole = AluGeoUtil.filterHoleLessMore(this._lrp['x_xoz_offX'], w - bkd, holes);
        holes = AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c1kk"], w, 2, this._lrp, "p_c1kk", Math.abs(filterHole.length - holes.length));
        holes = AluGeoUtil.reverseHole(w, holes);

        // AluGeoUtil.filterHoleLessMore(this._lrp['z_xoz_offX'], w - bkd, AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c1kk"],0))

        let h = new HoleMeta(bkd, b_dis, filterHole, "x");
        let c = new CreateMeta(t, front, back, h);
        let result = AluGeoUtil.createBoardWithHole(c);


        //绕x, y旋转90度
        let xr = 0.5 * Math.PI;
        let r = (-1 * (+this._lrp.angle1)) / 180 * Math.PI;

        let q = new Quaternion();
        let v = new Vector3();
        let a = new Vector3();

        for (let i: number = 0; i < result.vertices.length; i += 3) {
            let x = result.vertices[i];
            let y = result.vertices[i + 1];
            let z = result.vertices[i + 2];

            q.setFromAxisAngle(a.set(1, 0, 0), xr);
            v.set(x, y, z).applyQuaternion(q);

            q.setFromAxisAngle(a.set(0, 1, 0), r);
            v.set(v.x, v.y, v.z - l).applyQuaternion(q);

            result.vertices[i] = v.x;
            result.vertices[i + 1] = v.y;
            result.vertices[i + 2] = v.z;
        }


        let count = this.geometryMeta.vertices.length;
        this.geometryMeta.indices.push(...result.indices.map((value) => { value += count / 3; return value }));
        this.geometryMeta.vertices.push(...result.vertices);
    }


    /** xoy板(长2高)*/
    private xoy() {
        let t = +this._lrp.bkT;
        let w = +this._lrp.L2 - this._lrp['x_xoz_offX'];
        let l = +this._lrp.H - t;
        let r = (-1 * (+this._lrp.angle1));
        let bkd = (+this._lrp.BKDia) * 0.5;
        let b_dis = +this._lrp["p_c2gkbj"];

        let hr = (r * 0.5) / 180 * Math.PI;
        let zyr = Math.abs(Math.tan(hr));
        let zw = zyr == 0 ? 0 : t / zyr;

        let back = [
            0, 0, 0, w, 0, 0, w, l, 0, 0, l, 0,
        ];

        let front = [
            0, 0, t, w, 0, t, w, l, t, 0, l, t,
        ];

        // let h = new HoleMeta(bkd, b_dis, AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c2gk"],0), "x");
        let c = new CreateMeta(t, front, back, null);
        let result = AluGeoUtil.createBoardWithHole(c);

        for (let i: number = 0; i < result.vertices.length; i += 3) {
            result.vertices[i] += this._lrp['x_xoz_offX'];
            result.vertices[i + 1] -= +this._lrp.H;
            result.vertices[i + 2] += (+this._lrp.W2 - t);
        }


        let count = this.geometryMeta.vertices.length;
        this.geometryMeta.indices.push(...result.indices.map((value) => { value += count / 3; return value }));
        this.geometryMeta.vertices.push(...result.vertices);
    }


    /** zoy板(长1高)*/
    private zoy() {
        let t = +this._lrp.bkT;
        let w = +this._lrp.L1 - this._lrp['z_xoz_offX'];
        let l = +this._lrp.H - t;
        let bkd = (+this._lrp.BKDia) * 0.5;
        let b_dis = +this._lrp["p_c1gkbj"];


        let back = [
            0, 0, 0, w, 0, 0, w, l, 0, 0, l, 0,
        ];

        let front = [
            0, 0, t, w, 0, t, w, l, t, 0, l, t,
        ];

        // let h = new HoleMeta(bkd, b_dis, AModelFmulaUtils.getHolesbyExpress(this._lrp["p_c1gk"],0), "x");
        let c = new CreateMeta(t, front, back, null);
        let result = AluGeoUtil.createBoardWithHole(c);

        // let xr = -0.5 * Math.PI;
        let r = (-1 * (+this._lrp.angle1)) / 180 * Math.PI;

        let q = new Quaternion();
        q.setFromAxisAngle(new Vector3(0, 1, 0), r);
        let v = new Vector3();


        for (let i: number = 0; i < result.vertices.length; i += 3) {

            let x = result.vertices[i];
            let y = result.vertices[i + 1];
            let z = result.vertices[i + 2];

            v.set(x, y, z).applyQuaternion(q);

            +this._lrp.L2 - this._lrp['x_xoz_offX'] + t
            result.vertices[i] = v.x + this._lrp['x_xoz_offX'];
            result.vertices[i + 1] = v.y - +this._lrp.H;
            result.vertices[i + 2] = v.z + +this._lrp.W2;
        }


        let count = this.geometryMeta.vertices.length;
        this.geometryMeta.indices.push(...result.indices.map((value) => { value += count / 3; return value }));
        this.geometryMeta.vertices.push(...result.vertices);
    }


    /** 弧*/
    private r_com() {
        let rr = AluGeoUtil.getRadiusPath(+this._lrp.W2, +this._lrp.H, +this._lrp.bkT, +this._lrp.arcR);
        let tt = AluGeoUtil.getRadiusPath(+this._lrp.W1, +this._lrp.H, +this._lrp.bkT, +this._lrp.arcR);

        this.x_r_com(rr);
        this.z_r_com(tt);

        //处理交点的弧线
        let a = rr[0];
        let a1 = rr[1];
        let b = tt[0];
        let b1 = tt[1];

        let cc = [];
        let cc1 = [];



        let tr = this._lrp['x_xoz_offX'] / +this._lrp.W2;

        // let max =  -Infinity;

        for (let i: number = 0; i < a.length; i += 3) {
            let y = a[i + 1];
            let z = a[i + 2];

            let x = z * tr;
            cc.push(x, y, z);
            // if(max < x){
            //     max = x;
            // }

            let yy = a1[i + 1];
            let zz = a1[i + 2];
            let xx = zz * tr;
            cc1.push(xx, yy, zz);
        }

        this.b_r_com(a, b, cc);
        this.b_r_com(a1, b1, cc1, true);
    }

    private b_r_com(aa, bb, cc, reverse = false) {
        let vec = [];
        let indics = [];
        let no = this.geometryMeta.vertices.length / 3;

        for (let i: number = 0; i <= cc.length - 6; i += 3) {
            let a1 = [aa[i], aa[i + 1], aa[i + 2]];
            let a2 = [aa[i + 3], aa[i + 4], aa[i + 5]];

            let b1 = [bb[i], bb[i + 1], bb[i + 2]];
            let b2 = [bb[i + 3], bb[i + 4], bb[i + 5]];

            let c1 = [cc[i], cc[i + 1], cc[i + 2]];
            let c2 = [cc[i + 3], cc[i + 4], cc[i + 5]];

            vec.push(...a1, ...a2, ...c2, ...c1);
            indics.push(no, no + 1, no + 2);
            indics.push(no + 2, no + 3, no);
            no += 4;

            let c3 = [cc[i], cc[i + 1], cc[i + 2]];
            let c4 = [cc[i + 3], cc[i + 4], cc[i + 5]];

            vec.push(...b1, ...b2, ...c4, ...c3);
            indics.push(no, no + 3, no + 2);
            indics.push(no + 2, no + 1, no);
            no += 4;
        }

        reverse && indics.reverse();
        this.geometryMeta.indices.push(...indics);
        this.geometryMeta.vertices.push(...vec);
    }

    private x_r_com(rr) {

        let a = rr[0] as Array<number>;
        let b = rr[1] as Array<number>;

        let q = new Quaternion();
        let v = new Vector3();
        let axis = new Vector3();

        for (let i: number = 0; i < a.length; i += 3) {
            a[i] -= +this._lrp.W2;
            b[i] -= +this._lrp.W2;

            q.setFromAxisAngle(axis.set(0, 1, 0), 0.5 * Math.PI);
            v.set(a[i], a[i + 1], a[i + 2]).applyQuaternion(q);
            a[i] = v.x; a[i + 1] = v.y; a[i + 2] = v.z;

            v.set(b[i], b[i + 1], b[i + 2]).applyQuaternion(q);
            b[i] = v.x; b[i + 1] = v.y; b[i + 2] = v.z;

            q.setFromAxisAngle(axis.set(0, 0, 1), -1 * Math.PI);
            v.set(a[i], a[i + 1], a[i + 2]).applyQuaternion(q);
            a[i] = v.x; a[i + 1] = v.y; a[i + 2] = v.z;

            v.set(b[i], b[i + 1], b[i + 2]).applyQuaternion(q);
            b[i] = v.x; b[i + 1] = v.y; b[i + 2] = v.z;

            a[i] += +this._lrp.L2;
            b[i] += +this._lrp.L2;
        }


        let vec = [];
        let indics = [];
        // let no = 0;
        //2个侧面
        let no = this.geometryMeta.vertices.length / 3;

        for (let i: number = 0; i < a.length - 3; i += 3) {
            let a1 = [a[i], a[i + 1], a[i + 2]];
            let a2 = [a[i + 3], a[i + 4], a[i + 5]];

            let b1 = [b[i], b[i + 1], b[i + 2]];
            let b2 = [b[i + 3], b[i + 4], b[i + 5]];

            vec.push(...a1, ...a2, ...b1, ...b2);
            indics.push(no, no + 1, no + 2);
            indics.push(no + 2, no + 1, no + 3);
            no += 4;
        }


        this.geometryMeta.indices.push(...indics.reverse());
        this.geometryMeta.vertices.push(...vec);
    }

    private z_r_com(rr) {

        let a = rr[0] as Array<number>;
        let b = rr[1] as Array<number>;

        let q = new Quaternion();
        let v = new Vector3();
        let axis = new Vector3();

        let r = (-1 * (+this._lrp.angle1)) / 180 * Math.PI;

        for (let i: number = 0; i < a.length; i += 3) {
            a[i] -= +this._lrp.W1;
            b[i] -= +this._lrp.W1;

            q.setFromAxisAngle(axis.set(0, 1, 0), -0.5 * Math.PI);
            v.set(a[i], a[i + 1], a[i + 2]).applyQuaternion(q);
            a[i] = v.x; a[i + 1] = v.y; a[i + 2] = v.z;

            v.set(b[i], b[i + 1], b[i + 2]).applyQuaternion(q);
            b[i] = v.x; b[i + 1] = v.y; b[i + 2] = v.z;

            q.setFromAxisAngle(axis.set(0, 0, 1), -1 * Math.PI);
            v.set(a[i], a[i + 1], a[i + 2]).applyQuaternion(q);
            a[i] = v.x; a[i + 1] = v.y; a[i + 2] = v.z;

            v.set(b[i], b[i + 1], b[i + 2]).applyQuaternion(q);
            b[i] = v.x; b[i + 1] = v.y; b[i + 2] = v.z;

            a[i] += +this._lrp.L1;
            b[i] += +this._lrp.L1;

            q.setFromAxisAngle(axis.set(0, 1, 0), r);
            v.set(a[i], a[i + 1], a[i + 2]).applyQuaternion(q);
            a[i] = v.x; a[i + 1] = v.y; a[i + 2] = v.z;

            v.set(b[i], b[i + 1], b[i + 2]).applyQuaternion(q);
            b[i] = v.x; b[i + 1] = v.y; b[i + 2] = v.z;
        }


        let vec = [];
        let indics = [];
        // let no = 0;
        //2个侧面
        let no = this.geometryMeta.vertices.length / 3;

        for (let i: number = 0; i < a.length - 3; i += 3) {
            let a1 = [a[i], a[i + 1], a[i + 2]];
            let a2 = [a[i + 3], a[i + 4], a[i + 5]];

            let b1 = [b[i], b[i + 1], b[i + 2]];
            let b2 = [b[i + 3], b[i + 4], b[i + 5]];

            vec.push(...a1, ...a2, ...b1, ...b2);
            indics.push(no, no + 1, no + 2);
            indics.push(no + 2, no + 1, no + 3);
            no += 4;
        }


        this.geometryMeta.indices.push(...indics);
        this.geometryMeta.vertices.push(...vec);
    }


    /**设置参数 */
    private setParams(data: AIBasicParams) {
        this._lrp = data;

        // +this._lrp.arcR = 300;
        // +this._lrp.bkT = 10;
        // +this._lrp.L2 = 800;
        // +this._lrp.W2 = 300;
        // +this._lrp.L1 = 800;
        // +this._lrp.W1 = 400;
        // +this._lrp.angle1 = 0;
        // +this._lrp.H = 300;

        // +this._lrp.arcR = +data.arcR;
        // +this._lrp.bkT = +data.bkT;
        // +this._lrp.L2 = +data.L2;
        // +this._lrp.W2 = +data.W2;
        // +this._lrp.L1 = +data.L1;
        // +this._lrp.W1 = +data.W1;
        // +this._lrp.angle1 = -1 * (+data.angle1);
        // +this._lrp.H = +data.H;

        //转锐角？
        let mr = (-1 * (+this._lrp.angle1)) - (-90);
        let rr = mr / 180 * Math.PI;
        let tr = Math.abs(mr) == 90 ? 0 : Math.tan(rr);
        let cr = Math.cos(rr);

        //x /cr + h * tr
        let ww = (Math.abs(mr) == 90 ? 0 : +this._lrp.W1 / cr) + +this._lrp.W2 * tr;
        let ww1 = (Math.abs(mr) == 90 ? 0 : +this._lrp.W2 / cr) + +this._lrp.W1 * tr;

        this._lrp['x_xoz_offX'] = ww;
        this._lrp['z_xoz_offX'] = ww1;
    }

}